package com.thkj.aop;

import com.thkj.entity.LogInfo;
import com.thkj.service.ISysLogService;
import com.thkj.util.RmLoginUserInfo;
import com.thkj.util.RmUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

@Aspect
public class SysAopLog {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private ISysLogService sysLogService;

    private Date visitTime; //开始时间
    private static final Logger logger = LoggerFactory.getLogger(SysAopLog.class);

    @Pointcut("execution(* com.thkj.controller.*.*(..))&& !execution(* com.thkj.controller.UserAction.*(..)) ")
    public void controllerAspect() {
    }

    //前置通知  主要是获取开始时间，执行的类是哪一个，执行的是哪一个方法
    @Before("execution(* com.thkj.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime = new Date();//当前时间就是开始访问的时间
    }

    /**
     * 方法调用后触发 , 记录正常操作
     */
    @AfterReturning("controllerAspect()")
    public void after(JoinPoint joinPoint) throws ClassNotFoundException {
        try {
            long time = new Date().getTime() - visitTime.getTime(); //获取访问的时长
            // 用户id
            String userId = getUSerMsg().getUserId();
            //用户Name
            String username = getUSerMsg().getUserName();

            // 用户IP
            String ip = request.getRemoteAddr();
            // 控制器名
            String targetName = getMethodDesc(joinPoint).getController();
            // 方法名
            String methodName = getMethodDesc(joinPoint).getMethod();
            // 操作说明
            String operteContent = getMethodDesc(joinPoint).getOperateContent();
            LogInfo logInfo = new LogInfo();
            logInfo.setUserId(userId);
            logInfo.setUsername(username);
            logInfo.setIp(ip);
            logInfo.setOperateContent(operteContent);
            logInfo.setMethod(methodName);
            logInfo.setExecutionTime(time);
            logInfo.setVisitTime(visitTime);
            logInfo.setController(targetName);

            sysLogService.save(logInfo);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("日志异常报错=AfterReturning=" + e.getMessage());
        }
    }

    /**
     * 发生异常，走此方法
     */
    @AfterThrowing(pointcut = "controllerAspect()", throwing = "e")
    public void AfterThrowing(JoinPoint joinPoint, Throwable e) {
        try {
            // 用户id
            String userId = getUSerMsg().getUserId();
            //用户Name
            String username = getUSerMsg().getUserName();
            // 用户IP
            String ip = request.getRemoteAddr();
            // 控制器名
            String targetName = getMethodDesc(joinPoint).getController();
            // 方法名
            String methodName = getMethodDesc(joinPoint).getMethod();
            // 操作说明
            String operteContent = getMethodDesc(joinPoint).getOperateContent();
            String url = request.getRequestURL().toString();
            LogInfo logInfo = new LogInfo();
            String exMsg = e.getCause().toString();
            if (exMsg != null) {
                int type = 2;
                logInfo.setUserId(userId);
                logInfo.setUsername(username);
                logInfo.setIp(ip);
                logInfo.setOperateContent(operteContent);
                logInfo.setMethod(methodName);
                logInfo.setController(targetName);
                logInfo.setType(type);
                logInfo.setVisitTime(new Date());
                logInfo.setUrl(url);
                logInfo.setExMsg(exMsg);
                sysLogService.save(logInfo);
            }
        } catch (Exception e1) {
            logger.error("日志异常报错=AfterThrowing=" + e1.getMessage());
        }
    }

    /**
     * 获取 注解中对方法的描述
     *
     * @return
     * @throws ClassNotFoundException
     */
    public LogInfo getMethodDesc(JoinPoint joinPoint) throws ClassNotFoundException {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String operteContent = "";
        String url = request.getRequestURL().toString();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    // 操作说明
                    // operteContent = method.getAnnotation(ArchivesLog.class).operteContent();
                    break;
                }
            }
        }
        LogInfo logInfo = new LogInfo();
        logInfo.setController(targetName);
        logInfo.setMethod(methodName);
        logInfo.setOperateContent(operteContent);
        logInfo.setUrl(url);
        return logInfo;
    }

    /**
     * 得到用户信息
     */
    public RmLoginUserInfo getUSerMsg() {
        RmLoginUserInfo loginUserInfo = RmUtil.getLoginUserFromCookie(request);
        return loginUserInfo;
    }
}
